<?php

namespace app\uniapp\controller;

use app\common\exception\MiException;
use app\common\job\Queue;
use app\common\service\CommonGoodsService;
use app\common\service\CommonOrderService;
use app\common\service\pay\WxpayService;
use app\common\service\CommonSiteConfigService;
use app\model\site\User;
use app\model\store\Goods;
use app\model\store\GoodsCart;
use app\model\store\Order;
use app\model\store\OrderItem;
use app\model\store\OrderRefund;
use app\model\store\UserCoupon;
use app\uniapp\middleware\CheckLogin;
use app\uniapp\service\OrderRefundItemService;
use app\uniapp\service\OrderRefundService;
use app\uniapp\service\OrderService;
use app\uniapp\service\UniAuthService;
use app\uniapp\service\UniReqService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbEventException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Db;
use think\Request;
use think\response\Json;

class OrderController extends UniController
{

    protected array $middleware = [
        CheckLogin::class,
    ];

    /**
     * @throws DbException
     */
    public function paginate(Request $request){
        $orderStatus = $request->param('order_status', '');
        $where = [
            ['user_id', '=', UniAuthService::instance()->getLoginId()]
        ];
        if ($orderStatus){
            $where[] = ['order_status', '=', $orderStatus];
        }
        $ser = OrderService::instance()->setWhere($where)->setOrder('create_time desc');
        return UniReqService::instance()->setService($ser)->setPaginate()->getResponse();
    }

    public function find(){
        return UniReqService::instance()->setService(OrderService::instance())->setFind()->getResponse();
    }



    /***
     * 根据传入的参数，准备真实的订单信息
     * @return Json
     * @throws MiException
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function prepare(): Json
    {
        $post = $this->post();
        $order = OrderService::instance()->prepare($post);

        return jsonSuccess([
            'info' => $order
        ]);

    }

    /**
     * 创建订单
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws MiException
     */
    public function create(): Json
    {
        // 启动事务
        Db::startTrans();
        try {

            $post = $this->post();
            $order = OrderService::instance()->prepare($post);
            $orderItems = $order['items'];
            unset($order['items']);
            $uid = UniAuthService::instance()->getLoginId();
            // 添加uid
            $order['user_id'] = $uid;
            $order['order_status'] = 'unpaid';
            $order['order_no'] = makeOrderNo();
            $user = User::find($uid);

            if ($order['points_num']){
                $payPrice = $order['total_price'] - $order['coupon_price'];
                // 验证积分是否足够
                $pointsConfig = CommonSiteConfigService::instance()->getConfigValue($order['site_id'], CommonSiteConfigService::POINTS);
                $needPoints = floor($payPrice * $pointsConfig['money_rate']);
                if ($needPoints != $order['points_num'] || $needPoints > $user->points){
                    throw new MiException("积分不足");
                }
                // 扣除积分（为简化取消订单的积分退还逻辑，这里不创建明细，付款后创建明细）
                User::where('id', $uid)->dec('points', $order['points_num'])->update();
            }

            // 修改优惠券使用状态为已使用
            if ($order['coupon_id']??0){
                UserCoupon::update(['is_has_use' => 1],['id'=>$order['coupon_id']]);
            }

            // 扣除样品基金（为简化取消订单的基金退还逻辑，这里不创建明细，付款后创建明细）
            if ($order['store_manager_price']??0){   // 扣除样品基金
                \app\model\store\StoreManager::where('user_id', $uid)->dec('balance', $order['store_manager_price'])->update();
            }

            // 创建订单
            $createOrder = OrderService::instance()->create($order);
            $createOrder->save();

            // 创建订单商品
            foreach ($orderItems as $item) {
                $item['order_id'] = $createOrder->id;
                $item['user_id'] = UniAuthService::instance()->getLoginId();
                $item['site_id'] = UniAuthService::instance()->getSiteId();
                OrderItem::create($item);

                // 商品库存处理（先判断是否下单减库存）
                $goods = Goods::lock(true)->find($item['goods_id']);
                if ($goods->dec_stock_type == 1){   // 下单减库存（增加销量）
                   CommonGoodsService::instance()->decStock($goods, $item['num'], $item['goods_sku_id']??0);
                }

            }

            // 如果是从购物车创建，删除购物车商品信息
            if ($order['create_type'] == 'cart'){
                GoodsCart::where('id', 'in', $order['cart_ids'])->delete();
            }

            // 发送队列消息（取消订单）
            $config = CommonSiteConfigService::instance()->getConfigValue(UniAuthService::instance()->getSiteId(), CommonSiteConfigService::STORE);
            $delay = $config['order_cancel_delay'];
            Queue::instance()->send('orderCancel',['order_id'=>$createOrder->id], $delay);

            // 提交事务
            Db::commit();
            return jsonSuccess([
                'info' => $createOrder
            ]);

        } catch (DbEventException $e) {
            // 回滚事务
            Db::rollback();
            throw new MiException(print_r($e->getTraceAsString()));
        }


    }

    /**
     * 编辑订单信息
     * @return Json
     */
    public function edit(): Json
    {
        $post = $this->post();
        $info = OrderService::instance()->update($post, ['id' => $post['id']]);
        return jsonSuccess([
            'info' => $info,
        ]);
    }

    /**
     * 订单支付
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws DataNotFoundException|MiException
     */
    public function pay(Request $request): Json
    {

        if (!$request->isPost()){
            return jsonError(REQUEST_ERROR);
        }

        Db::startTrans();
        try {
            $id = $this->post('order_id');
            $openid = $this->post('openid');
            $order = Order::lock(true)->find($id);
            $payType = $order->pay_type;
            $res = '';

            // 使用积分抵扣后付款金额为零
            if ($order->pay_price == 0){    // 付款金额为0
                $payType = 'points';    // 修改付款方式为 points
                if ($order->postage_price > 0) throw new MiException("付款金额错误");
                // 订单支付成功后的操作
                CommonOrderService::instance()->paySuccess('points', $order);
            }else{

                if ($payType == 'wx'){  // 微信支付
                    $config = CommonSiteConfigService::instance()->getWxPayConfig(UniAuthService::instance()->getSiteId());
                    $wxPayService = WxpayService::getInstance($config);
                    $notify = request()->domain() . '/common/public/wxPayNotify/id/'.$order->site_id;
                    $res = $wxPayService->jsapi($order->order_no, $order->pay_price, $openid, '购买商品', $notify);

                }elseif ($payType == 'balance'){    // 余额支付
                    // 直接调用付款成功后的功能逻辑
                    CommonOrderService::instance()->paySuccess('balance', $order);

                }
            }

            Db::commit();

            return jsonSuccess([
                'pay_type' => $payType,
                'pay' => $res,
            ]);

        }catch (\Exception $e){
            Db::rollback();
            throw $e;
        }

    }


    /**
     * 申请退款
     * @throws MiException
     */
    public function refundApply(Request $request): Json
    {
        if ($request->isPost()){

            Db::transaction(function () {
                $post = $this->post();
                $itemIdArr = $post['itemIdArr']??'';
                $orderId = $post['order_id']??'';
                $order = Order::find($orderId);
                $items = OrderItem::where('id', 'in', $itemIdArr)->lock(true)->select();
                $orderRefundNum = 0;
                // 创建退款单
                $orderRefund = OrderRefundService::instance()->create([
                    'order_id' => $order->id,
                    'order_refund_no' => makeOrderNo(),
                    'refund_type' => $post['refund_type'],
                    'user_id' => UniAuthService::instance()->getLoginId(),
                    'refund_price' => $post['amount'],
                    'user_note' => $post['note'],
                ]);
                foreach ($items as $item){
                    $orderRefundNum += $item->num;
                    OrderRefundItemService::instance()->create([
                        'order_refund_id' => $orderRefund->id,
                        'order_id' => $order->id,
                        'order_item_id' => $item->id,
                        'goods_id' => $item->goods_id,
                        'goods_image' => $item->goods_image,
                        'goods_title' => $item->goods_title,
                        'goods_sku' => $item->goods_sku,
                        'goods_sku_id' => $item->goods_sku_id,
                        'num' => $item->num,
                        'refund_price' => $item->pay_price,
                    ]);
                }
                // 更新退款商品数量
                OrderRefund::update(['num' => $orderRefundNum],['id'=>$orderRefund->id]);
            });

            return jsonSuccess();

        }else{
            throw new MiException("请求错误");
        }
    }

    /**
     * 取消订单
     * @return Json
     * @throws MiException
     */
    public function cancel(): Json
    {
        $id = $this->post('id');
        if (!$id) throw new MiException("订单不存在");
        OrderService::instance()->cancel($id);

        return jsonSuccess();

    }


    // 确认收货
    public function receive(): Json
    {
        $id = $this->param('order_id');
        CommonOrderService::instance()->receive($id);
        return jsonSuccess();
    }

}
